/**
 * 
 */
package com.autoscript.ui.helper;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.autoscript.ui.common.IPublicConst;
import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLContextBuilder;
import org.apache.http.conn.ssl.TrustStrategy;
import org.apache.http.entity.StringEntity;
import org.apache.http.entity.mime.HttpMultipartMode;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.DefaultHttpRequestRetryHandler;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.message.BasicHeader;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.net.ssl.SSLContext;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.Charset;
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.util.*;

/**
 * HttpClient工具类
 * 
 * @author longsebo
 */
public class HttpClientUtil {
	private static final Logger log = LoggerFactory.getLogger(HttpClientUtil.class);
	private static PoolingHttpClientConnectionManager pcm;//httpclient连接池

	static {
		pcm = new PoolingHttpClientConnectionManager();
		pcm.setMaxTotal(50);//整个连接池最大连接数
		pcm.setDefaultMaxPerRoute(50);//每路由最大连接数，默认值是2
	}
	/**
	 * 使用post 提交到url
	 * 
	 * @param url
	 *            目标url
	 * @param bodyData
	 *            表体数据
	 * @throws Exception
	 */
	public static String post(String url, Map<String, String> bodyData)
			throws Exception {
		// 定义httpClient的实例
		CloseableHttpClient httpclient = null;
		if(url.toLowerCase().startsWith("https")){
			httpclient = createSSLClientDefault();
		}else{
			httpclient = HttpClients.createDefault();
		}
		String retVal;
		try {
			HttpPost httpPost = new HttpPost(url);
			List<NameValuePair> nvps = new ArrayList<NameValuePair>();
			Iterator<String> itKeys = bodyData.keySet().iterator();
			while (itKeys.hasNext()) {
				String key = itKeys.next();
				String val = bodyData.get(key);
				nvps.add(new BasicNameValuePair(key, val));
			}
			httpPost.setEntity(new UrlEncodedFormEntity(nvps,
					IPublicConst.ENCODE_UTF_8));
			CloseableHttpResponse response2 = httpclient.execute(httpPost);

			try {
				// RmProjectHelper.logError("系统调试",response2.getStatusLine());
				HttpEntity entity2 = (HttpEntity) response2.getEntity();
				if (entity2 != null) {
					retVal = EntityUtils.toString(entity2, "UTF-8");
				} else {
					retVal = null;
				}
				// do something useful with the response body
				// and ensure it is fully consumed
				EntityUtils.consume(entity2);
				return retVal;
			} finally {
				response2.close();
			}
		} finally {
			//httpclient.close();
		}

	}

	public static String get(String url) throws IOException {

		String returnVal = "";
		// 定义httpClient的实例
		CloseableHttpClient httpclient = null;
		if(url.toLowerCase().startsWith("https")){
			httpclient = createSSLClientDefault();
		}else{
			httpclient = HttpClients.createDefault();
		}
		HttpGet httpGet = new HttpGet(url);

		RequestConfig requestConfig = RequestConfig.custom()
				.setSocketTimeout(2000).setConnectTimeout(2000).build();// 设置请求和传输超时时间
		httpGet.setConfig(requestConfig);
		try {
			CloseableHttpResponse response2 = httpclient.execute(httpGet);// 执行请求
			// RmProjectHelper.logError("response2:", response2);
			HttpEntity entity2 = (HttpEntity) response2.getEntity();
			if (entity2 != null) {

				returnVal = EntityUtils.toString(entity2, "UTF-8");

			} else {
				returnVal = null;
			}

		} catch (ClientProtocolException e) {

			// RmProjectHelper.logError("retVal", e.getMessage());
		} catch (IOException e) {
			// TODO Auto-generated catch block
			// RmProjectHelper.logError("retVal", e.getMessage());

		} finally {

			if (httpclient != null) {

				//httpclient.close();
			}

		}

		return returnVal;

	}

	public static Map<String, Object> parseJSON2Map(String bizData) {
		Map<String, Object> ret = new HashMap<String, Object>();

		try {
			JSONObject bizDataJson = JSONObject.parseObject(bizData);
			for (Object key : bizDataJson.keySet()) {
				Object value = bizDataJson.get(key);
				if (value instanceof JSONArray) {
					List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
					Iterator<Object> it = ((JSONArray) value).iterator();

					while (it.hasNext()) {
						JSONObject json2 = (JSONObject) it.next();
						list.add(parseJSON2Map(json2.toString()));
					}
					ret.put(String.valueOf(key), list);
				} else {
					ret.put(String.valueOf(key), String.valueOf(value));
				}
			}
		} catch (Exception e) {
			// RmProjectHelper.logError("系统异常", e);
		}
		return ret;
	}

	/**
	 * 使用post 提交到url
	 * 
	 * @param url
	 *            目标url
	 * @param postDataXML
	 *            表体数据
	 * @throws Exception
	 */
	public static String post(String url, String postDataXML) throws Exception {
		// 定义httpClient的实例
		CloseableHttpClient httpclient = null;
		if(url.toLowerCase().startsWith("https")){
			httpclient = createSSLClientDefault();
		}else{
			httpclient = HttpClients.createDefault();
		}
		
		String retVal;
		try {
			HttpPost httpPost = new HttpPost(url);
			RequestConfig requestConfig = RequestConfig.custom()
					.setSocketTimeout(2000).setConnectTimeout(2000).build();// 设置请求和传输超时时间
			httpPost.setConfig(requestConfig);
			StringEntity postEntity = new StringEntity(postDataXML, "UTF-8");
			httpPost.addHeader("Content-Type", "text/xml");
			httpPost.setEntity(postEntity);
			CloseableHttpResponse response2 = httpclient.execute(httpPost);

			try {
				// RmProjectHelper.logError("系统调试",response2.getStatusLine());
				HttpEntity entity2 = (HttpEntity) response2.getEntity();
				if (entity2 != null) {
					retVal = EntityUtils.toString(entity2, "UTF-8");
				} else {
					retVal = null;
				}
				// do something useful with the response body
				// and ensure it is fully consumed
				EntityUtils.consume(entity2);
				return retVal;
			} finally {
				response2.close();
			}
		} finally {
			//httpclient.close();
		}

	}

	/**
	 * 使用post 提交文件及参数到url
	 * 
	 * @param url
	 *            目标url
	 * @param bodyData
	 *            表体数据(传文件时，value设置为File对象）
	 * @throws Exception
	 */
	public static String postFiles(String url, Map<String, Object> bodyData)
			throws Exception {
		// 定义httpClient的实例
		CloseableHttpClient httpclient = null;
		if(url.toLowerCase().startsWith("https")){
			httpclient = createSSLClientDefault();
		}else{
			httpclient = HttpClients.createDefault();
		}
		String retVal;
		try {
			HttpPost httpPost = new HttpPost(url);
			// List<NameValuePair> nvps = new ArrayList<NameValuePair>();
			Iterator<String> itKeys = bodyData.keySet().iterator();
			MultipartEntityBuilder builder = MultipartEntityBuilder.create();
			builder.setCharset(Charset.forName(IPublicConst.ENCODE_UTF_8));
			builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);// 设置浏览器兼容模式
			while (itKeys.hasNext()) {
				String key = itKeys.next();
				Object val = bodyData.get(key);
				if (val != null) {
					// 是否为文件
					if (val instanceof File) {
						builder.addBinaryBody(key, (File) val);
					} else {
						builder.addTextBody(key, val.toString());
					}
				}
			}
			HttpEntity entity = builder.build();// 生成 HTTP POST 实体
			// httpPost.setEntity(new UrlEncodedFormEntity(nvps,
			// IPublicConst.ENCODE_UTF_8));
			httpPost.setEntity(entity);
			CloseableHttpResponse response2 = httpclient.execute(httpPost);

			try {
				// RmProjectHelper.logError("系统调试",response2.getStatusLine());
				HttpEntity entity2 = (HttpEntity) response2.getEntity();
				if (entity2 != null) {
					retVal = EntityUtils.toString(entity2,
							IPublicConst.ENCODE_UTF_8);
				} else {
					retVal = null;
				}
				// do something useful with the response body
				// and ensure it is fully consumed
				EntityUtils.consume(entity2);
				return retVal;
			} finally {
				response2.close();
			}
		} finally {
			//httpclient.close();
		}

	}

	/**
	 * 創建https連接
	 * 
	 * @return
	 */
	private  static CloseableHttpClient createSSLClientDefault() {
		try {
			SSLContext sslContext = new SSLContextBuilder().loadTrustMaterial(
					null, new TrustStrategy() {

						public boolean isTrusted(
								java.security.cert.X509Certificate[] arg0,
								String arg1) throws CertificateException {
							return true;
						}

					}).build();
			SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
					sslContext);
			return HttpClients.custom().setSSLSocketFactory(sslsf).build();
		} catch (KeyManagementException e) {
			e.printStackTrace();
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		} catch (KeyStoreException e) {
			e.printStackTrace();
		}
		return HttpClients.createDefault();
	}
	 /** 
     * 下载文件 
     *  
     * @param url 
     *            http://www.xxx.com/img/333.jpg 
     * @param destFileName 
     *            xxx.jpg/xxx.png/xxx.txt 
     * @throws ClientProtocolException 
     * @throws IOException 
     */  
    public static void downFile(String url, String destFileName)  
            throws ClientProtocolException, IOException {  
        // 生成一个httpclient对象  
    	CloseableHttpClient httpclient = null;
		if(url.toLowerCase().startsWith("https")){
			httpclient = createSSLClientDefault();
		}else{
			httpclient = HttpClients.createDefault();
		}  
        HttpGet httpget = new HttpGet(url);  
		CloseableHttpResponse response2 = httpclient.execute(httpget);// 执行请求  
        HttpEntity entity = response2.getEntity();  
        InputStream in = entity.getContent();  
        File file = new File(destFileName);  
        try {  
            FileOutputStream fout = new FileOutputStream(file);  
            int l = -1;  
            byte[] tmp = new byte[1024];  
            while ((l = in.read(tmp)) != -1) {  
                fout.write(tmp, 0, l);  
                // 注意这里如果用OutputStream.write(buff)的话，图片会失真，大家可以试试  
            }  
            fout.flush();  
            fout.close();  
        } finally {  
            // 关闭低层流。  
            in.close();  
        }  
        //httpclient.close();  
    }
    /**
     * 根据url和header获取数据
     * @param url
     * @param header
     * @return
     * @throws IOException
     */
	public static String getByHeader(String url,Map<String,String> header) throws IOException {

		String returnVal = "";
		// 定义httpClient的实例
		CloseableHttpClient httpclient = null;
		if(url.toLowerCase().startsWith("https")){
			httpclient = createSSLClientDefault();
		}else{
			//httpclient = HttpClients.createDefault();
			httpclient = HttpClients.custom().setRetryHandler(new DefaultHttpRequestRetryHandler(3, true)).setConnectionManager(pcm).build();
		}
		HttpGet httpGet = new HttpGet(url);

		RequestConfig requestConfig = RequestConfig.custom()
				.setSocketTimeout(20000).setConnectTimeout(20000).build();// 设置请求和传输超时时间
		httpGet.setConfig(requestConfig);
		Set<String> keyset = header.keySet();
		Header[] header1 = new Header[header.size()];
//		httpGet.setHeaders(null);
		int i=0;
		for(String key:keyset){
//			httpGet.addHeader(key, header.get(key).toString());
			header1[i++]=new BasicHeader(key, header.get(key).toString());
		}
		httpGet.setHeaders(header1);
		try {
			CloseableHttpResponse response2 = httpclient.execute(httpGet);// 执行请求
			// RmProjectHelper.logError("response2:", response2);
			HttpEntity entity2 = (HttpEntity) response2.getEntity();
			if (entity2 != null) {

				returnVal = EntityUtils.toString(entity2, "UTF-8");

			} else {
				returnVal = null;
			}
			System.out.println("return val:"+returnVal);
			log.info("send url:"+url, "response:"+returnVal);
		} catch (ClientProtocolException e) {
			 e.printStackTrace();
			 log.error("retVal", e);
		} catch (IOException e) {
			e.printStackTrace();
			log.error("retVal", e);

		} finally {

			if (httpclient != null) {

				//httpclient.close();
			}

		}

		return returnVal;

	}
	/**
	 * 使用post json数据 提交到url
	 *
	 * @param url
	 *            目标url
	 * @param postDataJson
	 *            表体json数据
	 * @throws Exception
	 */
	public static String postJson(String url, String postDataJson) throws Exception {
		// 定义httpClient的实例
		CloseableHttpClient httpclient = null;
		if(url.toLowerCase().startsWith("https")){
			httpclient = createSSLClientDefault();
		}else{
			httpclient = HttpClients.createDefault();
		}

		String retVal;
		try {
			HttpPost httpPost = new HttpPost(url);
			RequestConfig requestConfig = RequestConfig.custom()
					.setSocketTimeout(2000).setConnectTimeout(2000).build();// 设置请求和传输超时时间
			httpPost.setConfig(requestConfig);
			StringEntity postEntity = new StringEntity(postDataJson, "UTF-8");
			httpPost.addHeader("Content-Type", "application/json");
			httpPost.setEntity(postEntity);
			CloseableHttpResponse response2 = httpclient.execute(httpPost);

			try {
				// RmProjectHelper.logError("系统调试",response2.getStatusLine());
				HttpEntity entity2 = (HttpEntity) response2.getEntity();
				if (entity2 != null) {
					retVal = EntityUtils.toString(entity2, "UTF-8");
				} else {
					retVal = null;
				}
				// do something useful with the response body
				// and ensure it is fully consumed
				EntityUtils.consume(entity2);
				return retVal;
			} finally {
				response2.close();
			}
		} finally {
			//httpclient.close();
		}

	}
	/**
	 * 多次重试使用post json数据 提交到url
	 *
	 * @param url
	 *            目标url
	 * @param postDataJson
	 *            表体json数据
	 * @throws Exception
	 */
	public static String postJsonRetry(String url, String postDataJson,int timeout,int retryTimes) throws Exception {
		// 定义httpClient的实例
		CloseableHttpClient httpclient = null;
		if(url.toLowerCase().startsWith("https")){
			httpclient = createSSLClientDefault();
		}else{
			httpclient = HttpClients.createDefault();
		}

		String retVal;
		for(int i=0;i<retryTimes;i++) {
			try {
				HttpPost httpPost = new HttpPost(url);
				RequestConfig requestConfig = RequestConfig.custom()
						.setSocketTimeout(timeout).setConnectTimeout(timeout).build();// 设置请求和传输超时时间
				httpPost.setConfig(requestConfig);
				StringEntity postEntity = new StringEntity(postDataJson, "UTF-8");
				httpPost.addHeader("Content-Type", "application/json");
				httpPost.setEntity(postEntity);
				CloseableHttpResponse response2 = httpclient.execute(httpPost);

				try {
					// RmProjectHelper.logError("系统调试",response2.getStatusLine());
					HttpEntity entity2 = (HttpEntity) response2.getEntity();
					if (entity2 != null) {
						retVal = EntityUtils.toString(entity2, "UTF-8");
					} else {
						//retVal = null;
						Thread.sleep(1000);
						continue;
					}
					// do something useful with the response body
					// and ensure it is fully consumed
					EntityUtils.consume(entity2);
					return retVal;
				} catch (Exception e) {
					e.printStackTrace();
					System.out.println("重试第"+i+"次");
					Thread.sleep(1000);
					continue;
				} finally {
					response2.close();
				}
			}catch (Exception e) {
				e.printStackTrace();
				System.out.println("重试第"+i+"次");
				Thread.sleep(1000);
				continue;
			} finally {
				//httpclient.close();
			}
		}
		return "";
	}

}
